/********************************************************************
	TABAL ENGINE - 2012/11/13
	author:		Marc Cuscullola
	
	purpose:	Defines the method to render the renderable vertexs
*********************************************************************/
#pragma once

#ifndef __INDEXED_VERTEXS__INCLUDED_H__
#define __INDEXED_VERTEXS__INCLUDED_H__

#pragma warning (disable:4005)

#include "RenderableVertexs.h"
#include "Effects\EffectTechnique.h"
#include "RenderManager.h"
#include "VertexType.h"

template<class T>
class CIndexedVertexs : public CRenderableVertexs
{
public:
	//-------------------------------------------------
	CIndexedVertexs(CRenderManager* _pRM, void* _pVertexAddress, void*_pIndexAddress, uint32 _uVertexCount, uint32 _uIndexCount, Vertexs::VERTEX_TYPOLOGY _topology = Vertexs::TRIANGLE_LIST)
	{
		m_uVertexCount = _uVertexCount;
		m_uIndexCount = _uIndexCount;

		// Vertex Buffer
		D3D11_BUFFER_DESC bd;
		ZeroMemory(&bd, sizeof(bd));
		bd.Usage = D3D11_USAGE_DEFAULT;
		bd.ByteWidth = GetVertexSize() * _uVertexCount;
		bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
		bd.CPUAccessFlags = 0;

		D3D11_SUBRESOURCE_DATA InitData;
		ZeroMemory(&InitData, sizeof(InitData));
		InitData.pSysMem = _pVertexAddress;
		HRESULT hr = _pRM->GetDevice()->CreateBuffer(&bd, &InitData, &m_pVertexBuffer);
		assert(SUCCEEDED(hr));
		
		// Index Buffer
		bd.Usage = D3D11_USAGE_DEFAULT;
		bd.ByteWidth = GetIndexSize() * _uIndexCount;
		bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
		bd.CPUAccessFlags = 0;
		InitData.pSysMem = _pIndexAddress;
		hr = _pRM->GetDevice()->CreateBuffer(&bd, &InitData, &m_pIndexBuffer);
		assert(SUCCEEDED(hr));

		switch(_topology)
		{
		case Vertexs::TRIANGLE_LIST:
			{
				m_Topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
				break;
			}
		case Vertexs::TRIANGLE_STRIP:
			{
				m_Topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
				break;
			}
		}
	}

	//-------------------------------------------------
	~CIndexedVertexs()
	{

	}

	//-------------------------------------------------
	void Render(CRenderManager* _pRM, CEffectTechnique* _pTechnique) const
	{
		ID3D11DeviceContext* l_pDeviceContext = _pRM->GetDeviceContext();

		// Set Vertex Buffer
		UINT stride = sizeof(T);
		UINT offset = 0;
		l_pDeviceContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);

		// Set Index Buffer
		l_pDeviceContext->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);

		// Set topology
		l_pDeviceContext->IASetPrimitiveTopology(m_Topology);

		// Render
		_pTechnique->BeginRender();

		D3DX11_TECHNIQUE_DESC desc;
		_pTechnique->GetD3DTechnique()->GetDesc(&desc);
		ID3DX11EffectPass *l_pEffectPass;
		for(uint8 i=0; i<desc.Passes; ++i)
		{
			// Get the current pass
			l_pEffectPass = _pTechnique->GetD3DTechnique()->GetPassByIndex(i);
			assert(l_pEffectPass && l_pEffectPass->IsValid());

			l_pEffectPass->Apply(0, l_pDeviceContext);
			l_pDeviceContext->DrawIndexed(m_uIndexCount, 0, 0);
		}
	}

	//-------------------------------------------------
	inline uint16	GetVertexType() const	{ return T::GetVertexType(); }
	inline uint32	GetVertexSize()	const	{ return sizeof(T); }
	inline uint32	GetIndexSize()	const	{ return sizeof(uint16); }
};

#endif //__INDEXED_VERTEXS__INCLUDED_H__
